home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1998 March / Macworld (1998-03) (Disk 1).dmg / Shareware World / Info / For Developers / GhostScript 5.10 / MacGS-510 / files / gs_pdfwr.ps < prev    next >
Text File  |  1997-10-02  |  12KB  |  378 lines

  1. %    Copyright (C) 1996, 1997 Aladdin Enterprises.  All rights reserved.
  2. %
  3. % This file is part of Aladdin Ghostscript.
  4. % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  5. % or distributor accepts any responsibility for the consequences of using it,
  6. % or for whether it serves any particular purpose or works at all, unless he
  7. % or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  8. % License (the "License") for full details.
  9. % Every copy of Aladdin Ghostscript must include a copy of the License,
  10. % normally in a plain ASCII text file named PUBLIC.  The License grants you
  11. % the right to copy, modify and redistribute Aladdin Ghostscript, but only
  12. % under certain conditions described in the License.  Among other things, the
  13. % License requires that the copyright notice and this notice be preserved on
  14. % all copies.
  15.  
  16. % gs_pdfwr.ps
  17. % PDF writer additions to systemdict.
  18.  
  19. % This file should be included iff the pdfwrite "device" is included
  20. % in the executable.
  21.  
  22. % Redefine pdfmark to pass the data to the driver.
  23. % We use a pseudo-parameter named /pdfmark whose value is an array:
  24. %    key1 value1 ... CTM /type
  25. /.pdf===dict mark
  26.   /arraytype
  27.    { dup xcheck { ({) (}) } { ([) (]) } ifelse
  28.         % Stack: file obj left right
  29.       4 1 roll 2 index exch writestring () exch
  30.        { exch 2 index exch writestring
  31.      1 index exch pdfmark===only ( )
  32.        }
  33.       forall pop exch writestring
  34.    } bind
  35.   /packedarraytype 1 index
  36.   /dicttype
  37.    { 1 index (<<\n) writestring
  38.       { 2 index 3 -1 roll pdfmark===only 1 index ( ) writestring
  39.     1 index exch pdfmark===only dup (\n) writestring
  40.       }
  41.      forall (>>) writestring
  42.    } bind
  43. .dicttomark readonly def
  44. /pdfmark===only        % <file> <obj> pdfmark===only -
  45.  { .pdf===dict 1 index type .knownget { exec } { write==only } ifelse
  46.  } bind def
  47. /.pdfcvs        % <obj> .pdfcvs <string>
  48.  {        % We can't handle long values yet.
  49.    =string /NullEncode filter dup 2 index pdfmark===only
  50.    dup (\n\000) writestring closefile pop
  51.    =string (\n\000) search
  52.     { dup length string copy exch pop exch pop }
  53.     {        % The converted representation didn't fit.  Punt.
  54.       pop (???)
  55.     }
  56.    ifelse
  57.  } bind def
  58. /.pdfputparams        % <paramarray> <paramname> .pdfputparams <result...>
  59.  { currentdevice null false mark 6 -2 roll exch
  60.         % Don't allow the page device to get cleared....
  61.      {.putdeviceparams} 0 get .currentpagedevice pop {.setpagedevice} 0 get
  62.    3 array astore cvx exec
  63.  } bind def
  64. /pdfmark        % -mark- <key> <value> ... <markname> pdfmark -
  65.  { counttomark 1 add copy
  66.    matrix currentmatrix .pdfcvs exch ]
  67.    1 2 2 index length 3 sub { 2 copy 2 copy get .pdfcvs put pop } for
  68.    /pdfmark .pdfputparams
  69.    type /booleantype ne { cleartomark } if cleartomark
  70.  } odef
  71. userdict /pdfmark .undef
  72.  
  73. % Define setdistillerparams / currentdistillerparams.
  74. % Distiller parameters are currently treated as device parameters.
  75. /.distillerparamkeys mark
  76.         % General parameters
  77.   /ASCII85EncodePages { }
  78.   /AutoRotatePages { }
  79.   /CompatibilityLevel { }
  80.   /CompressPages { }
  81.   /CoreDistVersion { }
  82.   /DoThumbnails { }
  83.   /ImageMemory { }
  84.   /LZWEncodePages { }
  85.   /PreserveHalftoneInfo { }
  86.   /PreserveOPIComments { }
  87.   /PreserveOverprintSettings { }
  88.   /TransferFunctionInfo { }
  89.   /UCRandBGInfo { }
  90.   /UseFlateCompression { }
  91.         % Color sampled image parameters
  92.   /ColorACSDict { }
  93.   /AntiAliasColorImages { }
  94.   /AutoFilterColorImages { }
  95.   /ColorImageDepth { }
  96.   /ColorImageDict { }
  97.   /DownsampleColorImages { }
  98.   /ColorImageDownsampleType { }
  99.   /EncodeColorImages { }
  100.   /ColorImageFilter { }
  101.   /ColorImageResolution { }
  102.   /ColorConversionStrategy { }
  103.   /ConvertCMYKImagesToRGB { }
  104.   /ConvertImagesToIndexed { }
  105.         % Grayscale sampled image parameters
  106.   /GrayACSDict { }
  107.   /AntiAliasGrayImages { }
  108.   /AutoFilterGrayImages { }
  109.   /GrayImageDepth { }
  110.   /GrayImageDict { }
  111.   /DownsampleGrayImages { }
  112.   /GrayImageDownsampleType { }
  113.   /EncodeGrayImages { }
  114.   /GrayImageFilter { }
  115.   /GrayImageResolution { }
  116.         % Monochrome sampled image parameters
  117.   /AntiAliasMonoImages { }
  118.   /MonoImageDepth { }
  119.   /MonoImageDict { }
  120.   /DownsampleMonoImages { }
  121.   /MonoImageDownsampleType { }
  122.   /EncodeMonoImages { }
  123.   /MonoImageFilter { }
  124.   /MonoImageResolution { }
  125.         % Font embedding parameters
  126.   /AlwaysEmbed
  127.    { dup length 0 gt
  128.       { dup 0 get false eq
  129.          { dup length 1 sub 1 exch getinterval exch pop /~AlwaysEmbed exch
  130.          } if
  131.       } if
  132.    }
  133.   /NeverEmbed
  134.    { dup length 0 gt
  135.       { dup 0 get false eq
  136.          { dup length 1 sub 1 exch getinterval exch pop /~NeverEmbed exch
  137.          } if
  138.       } if
  139.    }
  140.   /EmbedAllFonts { }
  141.   /SubsetFonts { }
  142.   /MaxSubsetPct { }
  143. .dicttomark readonly def
  144. /.distillerdevice
  145.  { currentdevice .devicename /pdfwrite eq
  146.     { currentdevice }
  147.     { /pdfwrite finddevice }
  148.    ifelse
  149.  } bind def
  150. /setdistillerparams        % <dict> setdistillerparams -
  151.  { .distillerdevice null false mark 4 index
  152.     { //.distillerparamkeys 2 index .knownget { exec } { pop pop } ifelse }
  153.    forall .putdeviceparams
  154.    type /booleantype eq { pop } { cleartomark pop pop pop } ifelse pop
  155.  } odef
  156. /currentdistillerparams        % - currentdistillerparams <dict>
  157.  { .distillerdevice //.distillerparamkeys .getdeviceparams .dicttomark
  158.  } odef
  159.  
  160. % Patch the 'show' operators to pass the data to the device.
  161. % We use a pseudo-parameter named /show whose value is a dictionary:
  162. %    /String (str)
  163. %    /Values [cx cy char ax ay px py]
  164. %    /FontName /fontname
  165. %    /Matrix [xx xy yx yy tx ty]
  166. %    /Encoding [e0 .. e255]
  167. %      (optional, omitted if Encoding = BaseEncoding = StandardEncoding)
  168. %    /BaseEncoding [e0 ... e255] (optional, ditto)
  169. %    /CharStrings << charnames => anything >> (optional)
  170. % Note that the cx/y and ax/y values are in text space, not user space.
  171. % We also fill an empty path in order to get the clipping region and
  172. % current color set properly.  THIS IS A BIG HACK.
  173. /.pdfknownfonts mark
  174.   /Courier {StandardEncoding}
  175.   /Courier-Bold 1 index
  176.   /Courier-Oblique 1 index
  177.   /Courier-BoldOblique 1 index
  178.   /Helvetica 1 index
  179.   /Helvetica-Bold 1 index
  180.   /Helvetica-Oblique 1 index
  181.   /Helvetica-BoldOblique 1 index
  182.   /Times-Roman 1 index
  183.   /Times-Bold 1 index
  184.   /Times-Italic 1 index
  185.   /Times-BoldItalic 1 index
  186.   /Symbol {SymbolEncoding}
  187.   /ZapfDingbats {DingbatsEncoding}
  188. .dicttomark readonly def
  189. .currentglobal false .setglobal
  190. /.pdfknownids 50 dict def
  191. .setglobal
  192. /.findorigfont {    % <font> .findorigfont <origfont>
  193.             % Check for a known font with the same name,
  194.             % or one of the 14 known names,
  195.             % and the same UniqueID.
  196.   dup /UniqueID .knownget {
  197.     .pdfknownids 1 index .knownget {
  198.       exch pop dup null ne { true } { pop false } ifelse
  199.     } {            % We haven't looked up the UniqueID yet.
  200.             % Register the UniqueIDs of all fonts.
  201.       .FontDirectory {
  202.     exch pop dup /UniqueID .knownget {
  203.             % Stack: font uniqueid somefont somefontid
  204.       exch .pdfknownids 3 1 roll put
  205.     } {
  206.       pop
  207.     } ifelse
  208.       } forall
  209.             % Register the UniqueIDs of the 14 built-in fonts,
  210.             % to make sure they override any other fonts
  211.             % with the same UniqueIDs.
  212.       .pdfknownfonts {
  213.     pop
  214.     //systemdict /GlobalFontDirectory .knownget not { .FontDirectory } if
  215.     1 index .knownget {
  216.             % Stack: font uniqueid knownname knownfont
  217.       dup /UniqueID get exch .pdfknownids 3 1 roll put
  218.     } if pop
  219.       } forall
  220.             % Now see if the UniqueID is known.
  221.       .pdfknownids 1 index .knownget {
  222.     exch pop true
  223.       } {            % Record the UniqueID as not registered.
  224.     .pdfknownids exch null put false
  225.       } ifelse
  226.     } ifelse
  227.   } {            % This font has no UniqueID.
  228.     false
  229.   } ifelse
  230.             % Stack: font knownfont -true- | font -false-
  231.   {
  232.     exch pop
  233.   } {
  234.     { dup /OrigFont .knownget not { exit } if exch pop } loop
  235.   } ifelse
  236. } .bind def
  237. /setvmthreshold where { pop 1000000 setvmthreshold } if
  238. /.pdfdoshow        % <string> <cxd> <cyd> <char> <axd> <ayd> .pdfdoshow
  239.             %   <bool>
  240.  { mark /String 8 2 roll
  241. %vmstatus pop =only pop (, ) print
  242.    currentpoint transform 7 array astore /Values exch
  243.    currentfont .findorigfont
  244.         % Pass the original font name.
  245.    dup /FontName get
  246.    /FontName exch 3 -1 roll
  247.         % Concatenate the "quotient" of the current FontMatrix
  248.         % and the FontMatrix of the original font.
  249.         % Be sure to include any translation.
  250.    /Matrix
  251.      exch /FontMatrix get matrix invertmatrix
  252.      currentfont /FontMatrix get 1 index concatmatrix
  253.     % The matrix on the stack is now the font scaling matrix.
  254.     % Use it to inverse-transform cx/y and ax/y, so they will be in
  255.     % text space.
  256.     % Stack: mark /String <string> /Values <values> /FontName <fontname>
  257.     %   /Matrix <matrix>
  258.      4 index aload
  259.     %   ... cx cy char ax ay px py values
  260.      8 -2 roll 8 index idtransform 8 2 roll
  261.      5 -2 roll 8 index idtransform 5 2 roll
  262.      astore pop
  263.     % Now construct the combined matrix.
  264.      matrix currentmatrix dup 4 0 put dup 5 0 put dup concatmatrix
  265.     % Omit either encoding that is StandardEncoding.
  266.    /Encoding currentfont /Encoding .knownget not { [] } if
  267.      dup StandardEncoding eq { pop pop } if
  268.     % Make a reasonable guess at the base encoding.
  269.    /BaseEncoding .pdfknownfonts 6 index    % FontName
  270.      .knownget { exec } { StandardEncoding } ifelse
  271.    dup StandardEncoding eq {
  272.      pop pop
  273.    } {
  274.      currentfont /CharStrings .knownget { /CharStrings exch } if
  275.    } ifelse
  276. %vmstatus pop =only pop (, ) print
  277.    .dicttomark
  278.         % Set the clipping region and color in the output.
  279.         % This is another hack!
  280.    gsave newpath fill grestore
  281. %vmstatus pop =only pop (, ) print
  282.    /show .pdfputparams
  283. %vmstatus pop =only pop () = flush
  284.    dup type /booleantype eq
  285.     { pop pop true }
  286.     { dup /undefined eq
  287.        { cleartomark pop pop pop false }
  288.        { dup mark eq { /unknown /rangecheck } if
  289.      counttomark 4 add 1 roll cleartomark pop pop pop
  290.      /.pdfshow cvx exch signalerror
  291.        }
  292.       ifelse
  293.     }
  294.    ifelse
  295.  } .bind def
  296. /.pdfexecshow        % <proc> .pdfexecshow -
  297.  {        % Prevent output, but don't switch devices, since this
  298.         % confuses the Pattern caching mechanism.
  299.    gsave currentpoint newpath clip moveto exec currentpoint
  300.    grestore moveto
  301.  } .bind def
  302. /.pdfwrite?        % - .pdfwrite? <bool>
  303.  { currentdevice .devicename /pdfwrite eq
  304.    currentfont /FontType get 1 eq and
  305.  } .bind def
  306. % .pdfshow isn't an operator per se, but it still needs to be careful with
  307. % the stack so that the operators will have stack protection.
  308. /.pdfshow        % <string> <cx> <cy> <char> <ax> <ay> <showproc>
  309.             %   .pdfshow -
  310.  { 7 1 roll .pdfwrite?
  311.     { .pdfdoshow }
  312.     { 6 { pop } repeat false }
  313.    ifelse
  314.     { .pdfexecshow }
  315.     { exec }
  316.    ifelse
  317.  } .bind def
  318. /show
  319.  { dup 0 0 32 0 0 { show } .pdfshow
  320.  } .bind odef
  321. /ashow
  322.  { dup 0 0 32 6 index 6 index { ashow } .pdfshow
  323.  } .bind odef
  324. /widthshow
  325.  { 4 copy 4 1 roll 0 0 { widthshow } .pdfshow
  326.  } .bind odef
  327. /awidthshow
  328.  { 6 copy 6 1 roll { awidthshow } .pdfshow
  329.  } .bind odef
  330. /glyphshow where { pop } { (%END) .skipeof } ifelse
  331. /glyphshow
  332.  { .pdfwrite?
  333.     { currentfont /Encoding .knownget not { {} } if
  334.       0 1 2 index length 1 sub
  335.        {        % Stack: glyph encoding index
  336.      2 copy get 3 index eq { exch pop exch pop null exit } if pop
  337.        }
  338.       for null eq
  339.        { (X) dup 0 3 index put show pop }
  340.        { glyphshow }
  341.       ifelse
  342.     }
  343.     { glyphshow
  344.     }
  345.    ifelse
  346.  } .bind odef
  347. %END
  348. /.kshow1 {    % <index> <proc> <string> .kshow1
  349.   (X) dup 0 3 index 6 index get put show
  350.   2 index 1 index length 1 sub lt {
  351.     dup 3 index get exch 4 -1 roll 1 add get
  352.     3 -1 roll exec
  353.   } {
  354.     pop pop pop
  355.   } ifelse
  356. } .bind def
  357. /kshow {
  358.   .pdfwrite? {
  359.         % Construct a closure, and work character by character.
  360.     0 1 2 index length 1 sub 5 -2 roll
  361.     //.kshow1 /exec cvx 4 packedarray cvx for
  362.   } {
  363.     kshow
  364.   } ifelse
  365. } .bind odef
  366. % The remaining operators aren't implemented correctly.
  367. /xshow where {
  368.  pop /xshow { .pdfwrite? { 1 index show pop pop } { xshow } ifelse } .bind odef
  369. } if
  370. /yshow where {
  371.  pop /yshow { .pdfwrite? { 1 index show pop pop } { yshow } ifelse } .bind odef
  372. } if
  373. /xyshow where {
  374.  pop /xyshow { .pdfwrite? { 1 index show pop pop } { xyshow } ifelse } .bind odef
  375. } if
  376.